<?php
/**
 * Description: Instantiates objects.
 * Applications utilizing this file: Vanilla;
 *
 * Copyright 2003 Mark O'Sullivan
 * This file is part of Lussumo's Software Library.
 * Lussumo's Software Library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
 * Lussumo's Software Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License along with Vanilla; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * The latest source code is available at www.lussumo.com
 * Contact Mark O'Sullivan at mark [at] lussumo [dot] com
 *
 * @author Mark O'Sullivan
 * @copyright 2003 Mark O'Sullivan
 * @license http://lussumo.com/community/gpl.txt GPL 2
 * @package Framework
 * @version 1.1.2
 */

/**
 * Instantiates objects.
 *
 * Allows developer's to clone and change existing classes and
 * have their objects used throughout the application,
 * instead of the application default objects.
 *
 * @package Framework
 */
class ObjectFactory
{
    // An array containing name/value pairs mapping labels to class names
    private $ClassIndex = array();
    private $ControlStrings = array();
    static private $instance = null;

    static function getInstance()
    {
        if (self::$instance == null) {
            self::$instance = new ObjectFactory();
        }

        return self::$instance;
    }

    private function __construct()
    {
    }

    private function __clone()
    {
    }

    /**
     * Create a new object based on a class name. Will gracefully error out if
     * the class does not exist
     */
     public function NewObject($ClassLabel, $Param1 = '', $Param2 = '', $Param3 = '', $Param4 = '', $Param5 = '', $Param6 = '', $Param7 = '', $Param8 = '', $Param9 = '', $Param10 = '')
    {
        // If the class has not yet been defined, assume the class label is the class name
        $ClassName = !isset($this->ClassIndex[$ClassLabel]) ? $ClassLabel : $this->ClassIndex[$ClassLabel];
        if (!class_exists($ClassName)) {
            $context = Context::getInstance();
            $prefix      = $context->Configuration['LIBRARY_NAMESPACE_ARRAY'];
            $prefixCount = count($prefix);
            for ($i = 0; $i < $prefixCount; $i++) {
                $File = $context->Configuration['LIBRARY_PATH'];
                $File.= $prefix[$i] . '/';
                $File.= $ClassName.'.php';
                if (file_exists($File)) {
                    include $File;
                    break;
                }
            }

            // If it failed to find the class, throw a fatal error
            if (!class_exists($ClassName)) {
                $context->ErrorManager->AddError($context, 'ObjectFactory', 'NewObject', 'The "'.$ClassName.'" class referenced by "'.$ClassLabel.'" does not appear to exist.');
            }
        }

        return new $ClassName($Param1, $Param2, $Param3, $Param4, $Param5, $Param6, $Param7, $Param8, $Param9, $Param10);
    }

    /**
     * CreateControl
     *
     * @access public
     * @return mixed
     * @todo   Doublecheck if we need all those params.
     * @todo   Look into func_get_args()
     * @todo   Implement prefixes in Control/
     */
    public function CreateControl($ClassLabel, $Param1 = '', $Param2 = '', $Param3 = '', $Param4 = '', $Param5 = '', $Param6 = '', $Param7 = '', $Param8 = '', $Param9 = '', $Param10 = '')
    {
        // If the class has not yet been defined, assume the class label is the class name
        $ClassName = !isset($this->ClassIndex[$ClassLabel]) ? $ClassLabel : $this->ClassIndex[$ClassLabel];
        if (!class_exists($ClassName)) {
            $context = Context::getInstance();
            $prefix      = $context->Configuration['LIBRARY_NAMESPACE_ARRAY'];
            $prefixCount = count($prefix);
            for ($i = 0; $i < $prefixCount; $i++) {
                $File = $context->Configuration['LIBRARY_PATH'];
                $File.= $prefix[$i] .'/';
                $File.= 'Control/' . $ClassName . '.php';
                if (file_exists($File)) {
                    include $File;
                    break;
                }
            }

            // If it failed to find the class, throw a fatal error
            if (!class_exists($ClassName)) {
                $context->ErrorManager->AddError(
                        $context,
                        'ObjectFactory',
                        'CreateControl',
                        'The "' . $ClassName . '" control referenced by "' . $ClassLabel . '" does not appear to exist.'
                );
            }
        }
        return new $ClassName(
                    $Param1,
                    $Param2,
                    $Param3,
                    $Param4,
                    $Param5,
                    $Param6,
                    $Param7,
                    $Param8,
                    $Param9,
                    $Param10
        );
    }

    /**
     * For debugging, allow the current references to be written
     */
    function PrintReferences()
    {
        foreach ($this->ClassIndex as $Label => $Name) {
            echo '<div>'.$Label.': '.$Name.'</div>';
        }
    }

    function SetReference($ClassLabel, $ClassName = '')
    {
        if ($ClassName == '') {
            $ClassName = $ClassLabel;
        }
        $this->ClassIndex[$ClassLabel] = $ClassName;
    }
}